package com.bobo.sticky.notes.farmes;

import com.bobo.sticky.notes.backup.BackUpParse;
import com.bobo.sticky.notes.utils.LogBoBo;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Rectangle2D;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Screen;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;

/**
 * Note的控制器
 * @auhor bobo
 * @date 2022/1/22 21:31
 */
public class NoteController implements Initializable {

    // 备份文件夹
    public static final String BACKUP_PATH = "/backup/";
    public static final String BACKUP_FILE = "note_back_up";

    // 面板
    @FXML
    private AnchorPane pane;
    // 标题的遮挡层
    @FXML
    private Rectangle rectangleTitle;
    // 标题的输入框
    @FXML
    private TextField titleTextField;
    // 正文内容的输入框
    @FXML
    private TextArea contentTextArea;

    // 标题焦点监听事件
    private ChangeListener<Boolean> titleFocusedChangeListener = this :: titleFocusedChangeListener;
    // 正文内容焦点监听事件
    private ChangeListener<Boolean> contentFocusedChangeListener = this ::contentFocusedChangeListener;


    // 旧的正文消息，用来比较是否是相同的内容啥
    private String oldTextContent = null;

    // 释放按下ctrl并且未释放
    private boolean isCtrl = false;

    /**
     * 初始化方法
     * @param location
     * @param resources
     */
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // 添加焦点事件
        titleTextField.focusedProperty().addListener(titleFocusedChangeListener);
        // contentTextArea.focusedProperty().addListener(contentFocusedChangeListener);
    }


    /**
     *  面板鼠标点击事件
     *  点击面板时，标题遮挡层获取焦点
     * @param mouseEvent
     */
    public void paneMouseClicked(MouseEvent mouseEvent){
        rectangleTitle.requestFocus();
    }


    /**
     * 标题遮挡层的鼠标双击事件
     * 双击后，隐藏标题遮挡层，标题数据框获取焦点
     * 单击，选中标题遮挡层，并获取焦点
     * @param mouseEvent
     */
    public void rectangleTitleMouseClicked(MouseEvent mouseEvent){
        // 鼠标双击，隐藏标题遮挡层
        if (mouseEvent.getClickCount() == 2){
            // 标题遮挡层不显示
            rectangleTitle.setVisible(false);
            // 标题输入框获取焦点
            titleTextField.requestFocus();
        } else {
            rectangleTitle.requestFocus();
        }
    }


    /**
     * 标题焦点监听事件
     * 标题失去焦点时，显示标题遮挡层
     * @param observable
     * @param oldValue
     * @param newValue
     */
    private void titleFocusedChangeListener(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
        if (!newValue) {
            rectangleTitle.setVisible(true);
        }
    }

    /**
     * 标题按键事件
     * enter: 显示标题遮挡层，正文内容输入框获取焦点
     * esc: 显示标题遮挡层，标题遮挡层获取焦点
     * @param keyEvent
     */
    public void titleKeyPressed(KeyEvent keyEvent){
        // enter
        if ( keyEvent.getCode() == KeyCode.ENTER){
            // 标题遮挡层显示
            rectangleTitle.setVisible(true);
            // 正文内容输入框获取焦点
            contentTextArea.requestFocus();
            // 光标位置为最后一行的下一行，没有内容或者最后一行是换行时，就不需要移动光标了
            if(!contentTextArea.getText().endsWith("\n") && contentTextArea.getLength() != 0){
                contentTextArea.appendText("\n");
            }
        }
        // esc
        else if (keyEvent.getCode() == KeyCode.ESCAPE){
            // 标题遮挡层显示
            rectangleTitle.setVisible(true);
            // 标题遮挡层获取焦点
            rectangleTitle.requestFocus();
        }
    }


    /**
     * 正文内容焦点监听事件
     * 当失去焦点时，标题遮挡层获取焦点
     * @param observable
     * @param oldValue
     * @param newValue
     */
    private void contentFocusedChangeListener(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
        if (!newValue) {
            rectangleTitle.requestFocus();
            contentBackup();
        }
    }

    /**
     * 正文内容的按键按下事件
     * 按下esc后，正文失去焦点，标题遮挡层获取焦点
     * 按下ctrl键后不释放，等待下一个按键的事件
     * @param keyEvent
     */
    public void contentKeyPressed(KeyEvent keyEvent){
        if (keyEvent.getCode() == KeyCode.ESCAPE){
            // 标题遮挡层获取焦点，其实就是取消正文内容的焦点
            rectangleTitle.requestFocus();
            contentBackup();
        }
        // 按下ctrl键
        else if (keyEvent.getCode() == KeyCode.CONTROL){
            isCtrl = true;
        }
        // 按下s键
        else if (keyEvent.getCode() == KeyCode.S){
            // 按下ctrl键未释放
            if (isCtrl){
                contentBackup();
            }
        }
        // 按下b键，还原备份内容
        else if (keyEvent.getCode() == KeyCode.B){
            if (isCtrl){
                restoreBackUp();
            }
        }
    }

    /**
     * 正文内容的按键释放事件
     * @param keyEvent
     */
    public void contentKeyReleased(KeyEvent keyEvent){
        if (keyEvent.getCode() == KeyCode.CONTROL){
            isCtrl = false;
        }
    }

    /**
     * 正文备份
     */
    private void contentBackup(){
        // 保存数据
        // 新数据
        String newTextContent = contentTextArea.getText();
        // 新旧数据一致，不进行保存
        if (newTextContent.equalsIgnoreCase(oldTextContent)){
            return;
        }
        // 更新就数据
        oldTextContent = newTextContent;
        // 将新数据保存到对应文件中
        saveStrToFile(newTextContent);
    }

    /**
     * 将新数据保存到文件中
     * @param text 保存的数据内容
     */
    private void saveStrToFile(String text) {
        try {
            // 获取当前便签唯一标识
            // String id = this.pane.getScene().getRoot().getId();
            // 拼接路径
            // String pathFile = BACKUP_PATH + id;
            // 根据路径生成Path对象
            Path path = Paths.get(BACKUP_PATH + BACKUP_FILE);
            // 获取File对象
            File file = path.toFile();
            // 判断文件是否存在
            if (!file.exists()){
                File dir = new File(BACKUP_PATH);
                if (!dir.exists()){
                    dir.mkdirs();
                }
                // 创建文件
                file.createNewFile();
            }
            // 读取数据
            byte[] bytes = Files.readAllBytes(path);
            // 解析字节数组为字符串
            String fileStr = new String(bytes, "UTF-8");
            // 拼接字符串
            StringBuffer sb = new StringBuffer();
            // [{"content" : "text", "time" : "2022-02-15 10:42:06"},
            // sb.append("[");
            // sb.append("{");
            // sb.append("\"content\":");
            // sb.append("\"");
            // sb.append(text);
            // sb.append("\"");
            // sb.append(",");
            // sb.append("\"time\":");
            // sb.append("\"");
            // sb.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            // sb.append("\"");
            // sb.append("}");
            // // 文件无内容
            // if (StringUtils.isEmpty(fileStr)){
            //     sb.append("]");
            // }
            // // 文件已写入数据
            // else {
            //     sb.append(",");
            //     sb.append(fileStr.substring(1));
            // }

            // time \n content }
            sb.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            sb.append("\n");
            sb.append(text);
            sb.append("}");
            sb.append(fileStr);
            // 保存数据
            Files.write(path, sb.toString().getBytes("UTF-8"));
            LogBoBo.info(this.getClass(), "backup path = " + path.toAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加按钮鼠标点击事件
     * 增加一个新的便签
     * @param mouseEvent
     * @throws IOException
     */
    public void btnAddMouseClicked(MouseEvent mouseEvent) throws IOException {

        // Text text = new Text("123456789012345678901234567890");
        // textFlow.getChildren().add(text);

        // 将新建的note按照顺序排列
        // int len = BaseStage.STAGES.size();
        // len --;
        // Rectangle2D bounds = Screen.getPrimary().getVisualBounds();
        // double w = bounds.getWidth();
        // double h = bounds.getHeight();
        // double x = 100;
        // double y = 100;
        // int vw = (int) (w / 300);
        // int vh = (int) (h / 300);
        // if (vw * vh <= len){
        //     LogBoBo.info(this.getClass(), "-- bobo -- 屏幕放不下了");
        //     return ;
        // }
        // int yh = len / vw;
        // int ne = len - yh * vw;
        // x += ne * 300;
        // y += yh * 300;


        Rectangle2D bounds = Screen.getPrimary().getVisualBounds();
        double w = bounds.getWidth();
        double h = bounds.getHeight();
        double x = mouseEvent.getScreenX() + 100;
        double y = mouseEvent.getScreenY() + 100;
        if (x >= w - 300) {
            x = 300;
        }
        if (y >= h - 300){
            y = 300;
        }
        Note note = new Note();
        note.showNote(x, y);
    }

    /**
     * 添加按钮鼠标点击事件
     * 备份恢复
     * @param mouseEvent
     */
    public void btnBackUpMouseClicked(MouseEvent mouseEvent){
        restoreBackUp();
    }

    /**
     * 恢复备份内容到便签中
     */
    private void restoreBackUp(){
        List<String> parse = BackUpParse.parse(BACKUP_PATH + BACKUP_FILE);
        StringBuffer sb = new StringBuffer(contentTextArea.getText());
        for (String str : parse) {
            sb.append("\n");
            sb.append(str);
        }
        contentTextArea.setText(sb.toString());
    }

}
